package com.mlxg.untils.oss;

import com.aliyun.oss.OSS;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.mlxg.config.oss.ExhibitorAppConfig;
import com.mlxg.untils.file.FileUtils;
import com.mlxg.untils.file.MimeTypeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

@Slf4j
@Component
public class GeneralOSSUpLoadUtilss {

    @Autowired
    private ExhibitorAppConfig exhibitorAppConfig;

    @Autowired
    private OSS ossClient;

    private final String baseUrl = "http://gw.demo365.cc:18086"; // 本地路径访问前缀

    /**
     * 上传文件到 OSS，并返回 OSS URL
     *
     * @param source 本地相对路径或远程 URL
     * @param ossDir OSS 目标目录
     * @return 上传后的 OSS URL
     */
    public String uploadUrlToOss(String source, String ossDir) {
        if (StringUtils.isBlank(source)) return null;

        String bucketName = exhibitorAppConfig.getAliyunOss().getBucketName();
        String sourceUrl;

        if (source.startsWith("http://") || source.startsWith("https://")) {
            // 远程 URL，直接使用
            sourceUrl = source;
        } else {
            // 本地路径，拼接 baseUrl，不编码
            if (!source.startsWith("/")) {
                source = "/" + source;
            }
            sourceUrl = baseUrl + source;
        }

        log.info("准备上传文件，URL: {}", sourceUrl);

        try {
            String originalFilename = extractFileNameFromUrl(source);
            String fileExtension = getFileExtension(originalFilename);

            validateFileExtension(fileExtension);

            long fileSize = getFileSizeFromUrl(sourceUrl);
            validateFileSize(fileExtension, fileSize);

            try (InputStream inputStream = openUrlStream(sourceUrl)) {
                ObjectMetadata metadata = new ObjectMetadata();
                metadata.setContentType(MimeTypeUtils.getContextType(fileExtension.toLowerCase()));

                String ossFileName = ossDir + "/" + originalFilename;
                PutObjectRequest request = new PutObjectRequest(bucketName, ossFileName, inputStream, metadata);
                ossClient.putObject(request);

                String ossUrl = buildFileUrl(bucketName, exhibitorAppConfig.getAliyunOss().getEndpoint(), ossFileName);
                log.info("文件上传成功，OSS URL: {}", ossUrl);
                return ossUrl;
            }

        } catch (Exception e) {
            log.error("上传文件到 OSS 失败: {}", source, e);
            return null;
        }
    }

    private String extractFileNameFromUrl(String url) {
        if (StringUtils.isBlank(url)) throw new IllegalArgumentException("无效 URL");
        return url.substring(url.lastIndexOf("/") + 1);
    }

    private String getFileExtension(String filename) {
        if (StringUtils.isBlank(filename)) throw new IllegalArgumentException("无效文件名");
        int idx = filename.lastIndexOf(".");
        if (idx == -1 || idx == filename.length() - 1) throw new IllegalArgumentException("文件缺少扩展名");
        return filename.substring(idx + 1);
    }

    private InputStream openUrlStream(String sourceUrl) throws IOException {
        URL url = new URL(sourceUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(5000);
        conn.setReadTimeout(20000);

        if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
            throw new IOException("HTTP 请求失败，状态码: " + conn.getResponseCode());
        }
        return conn.getInputStream();
    }

    private long getFileSizeFromUrl(String sourceUrl) {
        try {
            URL url = new URL(sourceUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("HEAD");
            long len = conn.getContentLengthLong();
            if (len <= 0) {
                log.warn("无法获取文件大小，将使用默认值");
                return FileUtils.MAX_DEFAULT_SIZE;
            }
            return len;
        } catch (Exception e) {
            log.warn("获取文件大小失败，将使用默认值: {}", sourceUrl, e);
            return FileUtils.MAX_DEFAULT_SIZE;
        }
    }

    private void validateFileExtension(String fileExtension) {
        if (!MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION.contains(fileExtension.toLowerCase())) {
            throw new IllegalArgumentException("仅支持文件类型: " + MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
        }
    }

    private void validateFileSize(String fileExtension, long fileSize) {
        if (MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION.contains(fileExtension.toLowerCase())
                && fileSize > FileUtils.MAX_FILE_SIZE) {
            throw new IllegalArgumentException("文件过大，超过允许最大值: " + FileUtils.MAX_FILE_SIZE);
        }
    }

    private String buildFileUrl(String bucketName, String endpoint, String fileName) {
        String cleanEndpoint = endpoint.replaceAll("^(http|https)://", "");
        return String.format("https://%s.%s/%s", bucketName, cleanEndpoint, fileName);
    }
}
